package com.modernyuanshiren;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class GameMap {
	private List<String> legends;
	private int[][] mapDatas;
	private int width,height;
	private Boolean isHorizonSymmetry,isVerticalSymmetry;

	private Map<Integer, List<IPosition>> dataMap;

	public GameMap(List<String> legends, int[][] mapDatas) {
		this.legends = legends;
		this.mapDatas = mapDatas;
		dataMap = new HashMap<>();
		this.width = mapDatas[0].length;
		this.height = mapDatas.length;
		this.isHorizonSymmetry = checkHorizonSymmetry();
		this.isVerticalSymmetry = checkVerticalSymmetry();
		for (int i = 0; i < mapDatas.length; i++) {
			for (int j = 0; j < mapDatas[i].length; j++) {
				dataMap.computeIfAbsent(mapDatas[i][j], k -> new ArrayList<>())
						.add(new Position(j, i));
			}
		}
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

	public List<IPosition> getAllPositions(String name) {
		int idx = legends.indexOf(name);
		if (idx == -1) {
			return Collections.emptyList();
		}
		return dataMap.get(idx);
	}

	public int getCountOf(String name) {
		int idx = legends.indexOf(name);
		if (idx == -1) {
			return 0;
		}
		return dataMap.get(idx).size();
	}

	public boolean is(IPosition position, String name) {
		if (position.getY() >= mapDatas.length || position.getY() < 0) {
			return false;
		}
		if (position.getX() >= mapDatas[position.getY()].length
				|| position.getX() < 0) {
			return false;
		}
		int idx = mapDatas[position.getY()][position.getX()];
		return idx != -1 && legends.get(idx).equals(name);
	}

	public boolean isOneOf(IPosition position, String... name) {
		if (position.getY() >= mapDatas.length || position.getY() < 0) {
			return false;
		}
		if (position.getX() >= mapDatas[position.getY()].length
				|| position.getX() < 0) {
			return false;
		}
		int idx = mapDatas[position.getY()][position.getX()];
		return idx != -1 && Arrays.asList(name).contains(legends.get(idx));
	}

	public boolean isNormalFloor(IPosition position) {
		if (position.getY() >= mapDatas.length || position.getY() < 0) {
			return false;
		}
		if (position.getX() >= mapDatas[position.getY()].length
				|| position.getX() < 0) {
			return false;
		}
		return mapDatas[position.getY()][position.getX()] == -1;
	}

	public boolean isHorizonSymmetry() {
		return this.isHorizonSymmetry;
	}

	private boolean checkHorizonSymmetry() {
		for (int i = 0; i < mapDatas.length; i++) {
			int cols = mapDatas[i].length;
			for (int j = 0; j < cols / 2; j++) {
				if(mapDatas[i][j]!=mapDatas[i][cols-1-j]) {
					return false;
				}
			}
		}
		return true;
	}
	
	public boolean isVerticalSymmetry() {
		return this.isVerticalSymmetry;
	}

	private boolean checkVerticalSymmetry() {
		int rows = mapDatas.length;
		for (int i = 0; i < mapDatas.length/2; i++) {
			for (int j = 0; j < mapDatas[i].length; j++) {
				if(mapDatas[i][j]!=mapDatas[rows-1-i][j]) {
					return false;
				}
			}
		}
		return true;
	}
}
